package com.steam.xbcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.steam.xbcc.constants.RedisCourseTypeConstants;
import com.steam.xbcc.domain.CourseType;
import com.steam.xbcc.enums.GlobalExceptionCode;
import com.steam.xbcc.mapper.CourseTypeMapper;
import com.steam.xbcc.service.ICourseTypeService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.steam.xbcc.util.AssertUtil;
import com.steam.xbcc.vo.CourseTypeCrumbVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author wt
 * @since 2022-10-07
 */
@Slf4j
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Override
    @Cacheable(cacheNames = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_CACHENAMES, key = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_KEY)
    public List<CourseType> treeData() {
        return tree();
    }

    @Override
    public List<CourseTypeCrumbVo> crumbs(Long courseTypeId) {
        CourseType courseType = selectById(courseTypeId);
        AssertUtil.isNotNull(courseType, GlobalExceptionCode.COURSE_TYPE_IS_NULL_ERROR);
        String path = courseType.getPath();
        AssertUtil.isNotEmpty(path, GlobalExceptionCode.COURSE_PATH_IS_NULL_ERROR);
        String[] split = path.split("\\.");
        List<CourseTypeCrumbVo> crumbs = new ArrayList<>();
        for (String ctId : split){
            CourseTypeCrumbVo courseTypeCrumbVo = new CourseTypeCrumbVo();
            CourseType ownerProductType = selectById(ctId);
            courseTypeCrumbVo.setOwnerProductType(ownerProductType);
            Wrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid", ownerProductType.getPid());
            List<CourseType> courseTypes = selectList(wrapper);
            courseTypeCrumbVo.setOtherProductTypes(courseTypes);
            crumbs.add(courseTypeCrumbVo);
        }
        return crumbs;
    }

    private List<CourseType> tree() {
        // 1.查询所有分类数据
        List<CourseType> courseTypes = selectList(null);
        // 将集合转换为map
        Map<Long, CourseType> courseTypeMap = courseTypes.stream().collect(Collectors.toMap(CourseType::getId, courseType -> courseType));
        // 2.遍历查询到的集合数据
        List<CourseType> treeData = new ArrayList<>();
        courseTypes.forEach(e->{
            if (e.getPid() != null && e.getPid().intValue() == 0){ // 如果等于0，那么意味着他是顶级父类
                treeData.add(e);
            }else { // 有父类，需要找到自己的父亲
                CourseType courseType = courseTypeMap.get(e.getPid());
                if (courseType != null){ // 万一儿子的pid是脏数据，那么就拿不到父亲
                    courseType.getChildren().add(e);
                }
            }
        });
        return treeData;
    }

    @Override
    @CacheEvict(cacheNames = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_CACHENAMES, key = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_KEY)
    public boolean insert(CourseType entity) {
        return super.insert(entity);
    }

    @Override
    @CacheEvict(cacheNames = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_CACHENAMES, key = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_KEY)
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }

    @Override
    @CacheEvict(cacheNames = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_CACHENAMES, key = RedisCourseTypeConstants.COURSE_TYPE_TREE_DATA_CACHE_KEY)
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }
}
